package com.mes.schedule.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.GenericGenerator;

import com.mes.basicdata.domain.Part;
import com.mes.basicdata.domain.WorkCenter;

/**
 * 工序任务
 * date: Jun 22, 2015 3:22:24 PM <br/>  
 * @author Administrator  
 * @version   
 * @since JDK 1.6
 * @add Annotation cswen 2017/3/15
 */

@Entity
@org.hibernate.annotations.Entity(dynamicInsert=false,dynamicUpdate=false)
@Table(name = "T_SCHEDULE_DETAIL")
public class SOperationTask extends STask implements Serializable {

	//author lcs add @id
	@Id
	@GenericGenerator(name="uuid", strategy="assigned")
	@Column(name="UUID")
	protected String uuid;
	
	@Transient
	protected Double transferBatchQty;
	@Transient
	protected Double processBatchQty = 0.0;
	@Transient
	protected Double processBatchRunTime;
	
	@Column(name = "WORKCENTERNAME")
	private String workCenterName;
	
	public String getWorkCenterName() {
		return workCenterName;
	}

	public void setWorkCenterName(String workCenterName) {
		this.workCenterName = workCenterName;
	}

	public Double getTransferBatchQty() {
		return transferBatchQty;
	}

	public void setTransferBatchQty(Double transferBatchQty) {
		this.transferBatchQty = transferBatchQty;
	}

	public Double getProcessBatchQty() {
		return processBatchQty;
	}

	public void setProcessBatchQty(Double processBatchQty) {
		this.processBatchQty = processBatchQty;
	}

	public Double getProcessBatchRunTime() {
		return processBatchRunTime;
	}

	public void setProcessBatchRunTime(Double processBatchRunTime) {
		this.processBatchRunTime = processBatchRunTime;
	}
	private static final long serialVersionUID = 1L;

	/**
	 * 草稿
	 */
	public final static int TASKSTATE_DRAG = 201; 
	/**
	 * 等待
	 */
	public final static int TASKSTATE_WAITING = 202; 
	/**
	 *  已分解
	 */	
	public final static int TASKSTATE_PREASSIGNED = 204; 
	/**
	 *  已计划
	 */
	public final static int TASKSTATE_READY = 205; 
	/**
	 *  已派工
	 */
	public final static int TASKSTATE_DISPATCHED = 206; 
	/**
	 *  已开始离线准备
	 */
	public final static int TASKSTATE_OFFLINEPREPARE_STARTED = 2061; 
	/**
	 *  已完成离线准备
	 */
	public final static int TASKSTATE_OFFLINEPREPARE_COMPLETED = 2069; 
	/**
	 *  已开始
	 */
	public final static int TASKSTATE_STARTED = 207; 
	/**
	 *  已完成在线准备，装卡完
	 */
	public final static int TASKSTATE_PREPARE_COMPLETED = 2071; 
	/**
	 * 已完成首件加工
	 */
	public final static int TASKSTATE_FIRSTCHECK_COMPLETED = 2072; 
	/**
	 *  已完成加工
	 */
	public final static int TASKSTATE_COMPLETED = 209; 
	/**
	 *  已取消
	 */
	public final static int TASKSTATE_CANCELED = 210; 
	/**
	 * 工序已交付入库
	 */
	public final static int TASKSTATE_DELIVERIED = 211; 
	/**
	 *  已暂停
	 */
	public final static int TASKSTATE_PAUSED = 208; 
	/**
	 *   已中断
	 */
	public final static int TASKSTATE_INTERRUPTED = 2081;
	
	/**
	 * 协作任务草稿
	 */
	public final static int COTASKSTATE_DRAG = 0; 
	/**
	 * 协作任务已经发布
	 */
	public final static int COTASKSTATE_PUBLISHED = 1; 
	/**
	 * 协作任务 已经接收
	 */
	public final static int COTASKSTATE_RECEIVED = 2; 
	/**
	 * 协作任务 已经拒绝
	 */
	public final static int COTASKSTATE_REFUSED = 3; 
	/**
	 * 协作任务 已经反馈
	 */
	public final static int COTASKSTATE_FEEDBACKED = 4; 
	/**
	 * 协作任务 已经取消
	 */
	public final static int COTASKSTATE_CANCELED = 5; 
	/**
	 * 手动已派 hba
	 */
	public final static int MANUAL_SCHEDULED = 1;
	
	@Override
	public Integer getTaskState() {
		if (this.taskState == null)
			return SOperationTask.TASKSTATE_READY;
		return super.getTaskState();
	}

	@Override
	public String getTaskType() {
		// TODO Auto-generated method stub
		if (this.taskType == null)
			return SOperationTask.TASKTYPE_NORMALTASK;
		return super.getTaskType();
	}
	/**
	 * 任务类型 正常工序
	 */
	public final static String TASKTYPE_NORMALTASK = "201"; 
	/**
	 * 任务类型  临时工序
	 */
	public final static String TASKTYPE_TEMPTASK = "206"; 
	/**
	 * 任务类型  协作工序
	 */
	public final static String TASKTYPE_COTASK = "222"; 
	/**
	 * 工序唯一号
	 */
	@Column(name = "OPERATION_ID")
	protected Float operationId;
	/**
	 * 父类零件任务唯一号
	 */
	@Column(name = "PARENTUID")
	protected String parentTaskUid;
	/**
	 * 父类零件任务
	 */
	@Transient
	protected SPartTask parentTask;
	
	@Transient
	protected int alarmLevel;
	/**
	 * 约束类型
	 */	
	@Transient
	protected int constraintType;
	/**
	 * 约束日期
	 */
	@Transient
	protected Date constraintDate;
	/**
	 * 工作中心唯一号
	 */
	@Column(name = "WORKCENTERUID")
	protected String workCenterUid;
	/**
	 * 不用于序列化
	 */
	@Transient
	protected transient WorkCenter workCenter;
	/**
	 * 设备类名称
	 */
	@Transient
	protected String deviceClassName;
	// protected Device deviceClassObject;
	/**
	 * 多线程访问
	 */
	@Transient
	protected volatile SDevice device;
	@Transient
	protected int indexForMultiCapacityDevice;
	/**
	 * 设备唯一号
	 */	
	@Column(name = "RESUID")
	protected String deviceUid;
	/**
	 * 最早开始
	 */
	@Column(name = "EARLYSTART")
	protected Date earlyStart;
	/**
	 * 最晚结束
	 */
	@Column(name = "LATEFINISH")
	protected Date lateFinish;
	/**
	 * 多线程访问  计划开始
	 */
	@Column(name = "SCHEDULESTART")
	protected volatile Date planStart;
	/**
	 * 多线程访问  计划结束
	 */
	@Column(name = "SCHEDULEFINISH")
	protected volatile Date planFinish;
	
	@Column(name = "BASESTART")
	protected Date baseStart;
	@Column(name = "BASEFINISH")
	protected Date baseFinish;
	/**
	 * 多线程访问  计划开始时段
	 */
	@Transient
	protected volatile int planStartSegment;
	/**
	 * 多线程访问  计划结束时段
	 */
	@Transient
	protected volatile int planFinishSegment;

	/**
	 * 前序计划开始
	 */
	@Transient
	protected Date prevPlanStart;
	/**
	 * 前序计划结束
	 */
	@Transient
	protected Date prevPlanFinish;
	/**
	 * 工序任务需要时间=准备+单件*数量
	 */
	@Transient
	protected Double estiTaskWork;
	/**
	 * 准备时间
	 */	
	@Column(name = "ESTIPRETIME")
	protected Double estiPreTime;
	/**
	 * 单件时间
	 */	
	@Column(name = "ESTIRUNTIME")
	protected Double estiRunTime;
	/**
	 * 拖期时间
	 */	
	@Column(name = "PREOPTIME")
	protected Double estiDelayTime;
	/**
	 * 工作中心唯一号
	 */
	//@Column(name = "WORKCENTERUID")
	@Transient
	protected String sWorkCenterUid;
	
	@Transient
	protected SWorkCenter sWorkCenter;
	/**
	 * 标识状态
	 */
	@Column(name = "ASSIGNSTATE")
	protected volatile Integer assignState; 
	/**
	 *  0-- 待调度任务
	 */
	public final static int ASSNSTATE_WAITING = 0;
	/**
	 *  1--已启动分配例程
	 */	
	public final static int ASSNSTATE_STARTED = 1;
	/**
	 *  2-- 已成功任务
	 */
	public final static int ASSNSTATE_SUCCESS = 2; 
	/**
	 *  3-- 已调度失败任务
	 */
	public final static int ASSNSTATE_FAILURE = 3;
	@Transient
	protected boolean ready;
	@Transient
	protected boolean warning;
	/**
	 *  成组工序任务
	 */	
	@Transient
	protected SGroupOperationTask groupTask;
	/**
	 *  成组工序任务唯一号
	 */		
	@Column(name = "GROUP_TASKUID")
	protected String groupTaskUid;
	@Transient
	protected boolean isPSOperation;
	@Transient
	protected int taskDistance;
	@Transient
	protected double waitTime;
	/**
	 *  工序任务前置连接
	 */	
	@Transient
	protected volatile Set<SOperationLink> predLinkSet = new HashSet<SOperationLink>();
	/**
	 *  工序任务后置连接
	 */	
	@Transient
	protected volatile Set<SOperationLink> succLinkSet = new HashSet<SOperationLink>();
	/**
	 *   前置任务字符串
	 */	
	@Transient
	protected String predOperationStr;
	/**
	 *   后置任务字符串
	 */	
	@Transient
	protected String succOperationStr;

	/**
	 *   可选资源列表,将其改造成map,同一设备只允许一条限制
	 */		
	@Transient
	protected Map<String, ResourceConstraint> alterResourceMap = new HashMap<String, ResourceConstraint>();
	/**
	 *   工序对某一设备指定的优先顺序
	 */	
	@Transient
	protected int assnPriority;
	@Transient
	protected Integer netDepth;
	@Transient
	protected int coTaskType;
	/**
	 * 计划首件开始时间
	 */
	@Transient
	protected Date planFirstCheckStart;
	/**
	 * 	计算松弛率时所使用的LateFinish
	 */
	@Transient
	protected Date calcLateFinish;
	/**
	 * 	计算松弛率时所使用的LateFinish,只是用作算法过渡
	 */
	@Transient
	protected Date calcEarlyStart;
	/**
	 * 	最早结束
	 */	
	@Transient
	protected Date calcEarlyFinish;
	/**
	 * 	调度中锁占用的时间段列表
	 */	
	@Transient
	protected List<Integer> useSegementList;
	/**
	 * 	 已分配的资源，可能是设备工作台组合，也可能是虚拟资源
	 */	
	@Transient
	protected Resource assignedResource;
	/**
	 * 	  true表示是否应用顺序公平策略
	 *    主要用于多代理应用程序
	 *    只在dtAssignManager中应用，应该移出
	 */	
	@Transient
	public List<ReentrantLock> taskTockenLocks;
	@Transient
	public ReentrantLock taskAssignLock = new ReentrantLock();

	/**
	 * 考核点 计算松弛时赋值
	 */
	@Transient
	protected CheckPoint checkPoint;
	/**
	 * 对应这个任务最长的reminawork 计算松弛时赋值
	 */
	@Transient
	protected Double remainWork;

	/**
	 * 实际调度顺序
	 */
	@Transient
	protected int scheduleOrder;

	/**
	 * 任务调度次数
	 */
	@Transient
	protected int scheduleCount;

	/**
	 * 是否允许取消分配// lqm todo 以后应该由更高级的取消惩罚代价替换
	 */
	@Transient
	protected volatile Boolean calAllowCancelAssign;

	/**
	 * 计算过程中的固定设备，主要用于两阶段算法
	 */
	@Transient
	protected String calFixedDeviceUid;
	
	/**
	 * 是否可以改变设备
	 */
	@Transient
	protected Boolean canChangeDevice=true;

	/**
	 * 手动未派 hba
	 */
	public final static int MANUAL_UNSCHEDULED = 0;
	/**
	 * 工序手动派工状态hba
	 */
	@Transient
	protected Integer manualScheduleState = MANUAL_UNSCHEDULED;
	
	public Integer getManualScheduleState() {
		return manualScheduleState;
	}

	public void setManualScheduleState(Integer manualScheduleState) {
		this.manualScheduleState = manualScheduleState;
	}
	/**
	 * 成员分段任务函数 lqm todo,分段任务也可能有链接，应该建立一个segemtntTask
	 */
	@Transient
	protected List<SOperationTaskSegement> segementTasks;

	public List<SOperationTaskSegement> getSegementTasks() {
		return segementTasks;
	}

	public void setSegementTasks(List<SOperationTaskSegement> segementTasks) {
		this.segementTasks = segementTasks;
	}

	public Date getCalcLateFinish() {
		return calcLateFinish;
	}

	public void setCalcLateFinish(Date calcLateFinish) {
		this.calcLateFinish = calcLateFinish;
	}

	@Override
	public Integer getDelayCost() {
		// 暂时工序任务直接取零件任务的优先级
		if (parentTask != null)
			return parentTask.getDelayCost();

		return super.getDelayCost();
	}

	@Override
	public Integer getPlanGrade() {
		if (parentTask != null)
			return parentTask.getPlanGrade();
		return super.getPlanGrade();
	}

	public final static int CONSTRAINTTYPE_TIMESTONE = 1;
	public final static int CONSTRAINTTYPE_LOCKED = 2;
	// protected String uuid;
	
	@Column(name = "DEPTID")
	protected String deptUid;
	@Transient
	protected String deptName;
	
	@Column(name = "MASTERSHOP")
	protected String masterShop;
	
	@Transient
	protected String masterShopName;
	
	@Column(name = "OPERATION_IDDESC", length = 50)
	protected String operationIdDesc;
	
	@Column(name = "OPUID")
	protected String opUid;
	
	@Column(name = "BATCHNUM")
	protected String batchNum;
	
	@Column(name = "DRAWINGID")
	protected String drawingId;
	@Transient
	protected String partName;
	
	@Column(name = "PART_NUMBER")
	protected String partUid;

	@Transient
	protected transient Part part;
	/**
	 *  班次数量
	 */
	@Column(name = "SHIFTS_COUNT")
	protected Double shiftsCount;
	/**
	 *  实际开始
	 */
	@Column(name = "ACTUALSTART")
	protected Date actualStart;
	/**
	 *  准备完成时间
	 */
	@Transient
	protected Date actualPrepareFinish;
	/**
	 *  首件完成时间
	 */
	@Transient
	protected Date actualFirstFinish;
	/**
	 *  实际结束
	 */	
	@Column(name = "ACTUALFINISH")
	protected Date actualFinish;
	
	@Transient
	protected Date predFinish;
	@Transient
	protected Date coPlanFinish;
	@Transient
	protected Date coPlanStart;

	@Column(name = "DEVICESEQ")
	protected Integer deviceSeq;
	/**
	 *  // 计算所用设备序列，主要用于移动瓶颈法
	 */		
	@Transient
	protected Integer calDeviceSeq;
	/**
	 *  // 成熟度
	 */	
	@Transient
	protected int maturity = 0;
	@Transient
	protected Boolean canSplit = true;
	
	/**
	 * 仅用于比较atc值
	 */
	@Transient
	protected double calAtcValue;
	/**
	 *  工序协作状态
	 */
	@Column(name = "COTASKSTATE")
	protected Integer coTaskState;
	/**
	 * 子任务
	 */
	@Transient
	protected List<SOperationTask> subTasks;

	// // 非常临时的字段，主要是甘特图的完成百分比日期还不会处理
	// private Date tmpPercentCompleteDate;
	//
	// public Date getTmpPercentCompleteDate() {
	// return tmpPercentCompleteDate;
	// }
	//
	// public void setTmpPercentCompleteDate(Date tmpPercentCompleteDate) {
	// this.tmpPercentCompleteDate = tmpPercentCompleteDate;
	// }

	public Boolean getCanSplit() {
		return canSplit;
	}

	public void setCanSplit(Boolean canSplit) {
		this.canSplit = canSplit;
	}

	public Date getActualStart() {
		return actualStart;

	}

	public boolean isGroupTask() {

		// 暂时用作判断
		if (this.batchNum.indexOf(",") > 0
				|| this.operationIdDesc.indexOf("/") > 0)
			return true;
		return false;
	}

	public boolean isFinished() {
		if (this.taskState != null) {
			if (this.taskState == TASKSTATE_COMPLETED
					|| this.taskState == TASKSTATE_DELIVERIED) {
				return true;
			}
		}
		return false;
	}

	public boolean isStarted() {
		if (this.taskState != null) {
			if (this.taskState == TASKSTATE_STARTED
					|| this.taskState == TASKSTATE_PREPARE_COMPLETED
					|| this.taskState == TASKSTATE_FIRSTCHECK_COMPLETED
					|| this.taskState == TASKSTATE_PAUSED) {
				return true;
			}
		}
		return false;
	}

	/*
	 * 是否正在运行 含已开始，已派工，已开始/完成进行离线准备，已中断
	 */
	public boolean isRunning() {
		if (this.taskState != null) {
			if (this.isStarted() || this.taskState == TASKSTATE_DISPATCHED
					|| this.taskState == TASKSTATE_OFFLINEPREPARE_STARTED
					|| this.taskState == TASKSTATE_OFFLINEPREPARE_COMPLETED
					|| this.taskState == TASKSTATE_INTERRUPTED) {
				return true;
			}
		}
		return false;
	}

	/*
	 * 是否正在运行 含已开始，已派工，已开始/完成进行离线准备，已中断 相当于已经固定设备
	 */
	public boolean isDispatched() {
		if (this.taskState != null) {
			if (this.taskState == TASKSTATE_DISPATCHED
					|| this.taskState == TASKSTATE_OFFLINEPREPARE_STARTED
					|| this.taskState == TASKSTATE_OFFLINEPREPARE_COMPLETED
					|| this.taskState == TASKSTATE_INTERRUPTED) {
				return true;
			}
		}
		return false;
	}

	public void setActualStart(Date actualStart) {
		this.actualStart = actualStart;
	}

	public Date getActualFinish() {
		return actualFinish;
	}

	public void setActualFinish(Date actualFinish) {
		this.actualFinish = actualFinish;
	}

	public void setCoTaskType(int coTaskType) {
		this.coTaskType = coTaskType;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return " 工序任务=" + this.taskUid + " 工序号=" + this.getDrawingId() + ","
				+ this.getBatchNum() + "," + this.operationIdDesc
				+ " taskname=" + this.taskName;

	}

	public String toFriendlyString() {
		// TODO Auto-generated method stub
		StringBuilder sb = new StringBuilder();
		sb.append("图号：");
		sb.append(this.getDrawingId());
		sb.append(" 批次：");
		sb.append(this.getBatchNum());
		sb.append(" 工序：");
		sb.append(this.operationIdDesc);
		sb.append(this.taskName);
		return sb.toString();

	}

	public SOperationTask() {
		super();
		this.canSplit = true;

	}

	// 协作任务类型
	public int getCoTaskType() {

		// if (scheme.getDeptUid().substring(0, 4).equals(
		// this.masterShop.substring(0, 4))) {
		// // cooperate with other sections
		// coTaskType=1 ;
		// } else if (scheme.getDeptUid().substring(0, 2).equals(
		// this.masterShop.substring(0, 2))) {
		// // cooperate with other shops
		// coTaskType =2;
		// } else {
		// // cooperate with other factories
		// coTaskType = 3;
		// }
		//		

		return coTaskType;
	}

	// public int getPriority() {
	// //暂时工序任务直接取零件任务的优先级
	// if(parentTask!=null)
	// return parentTask.getPriority();
	//
	// return priority;
	// }

	public Integer getNetDepth() {
		return netDepth;
	}

	public void setNetDepth(Integer netDepth) {
		this.netDepth = netDepth;
	}

	/*
	 * 产生前置任务工序字符串
	 */
	public void generatePredOperationStr() {
		predOperationStr = "";
		for (SOperationLink link : this.predLinkSet) {
			predOperationStr += link.getPredOperationTask()
					.getOperationIdDesc()
					+ ",";

		}
		if (predOperationStr.endsWith(","))
			predOperationStr = predOperationStr.substring(0, predOperationStr
					.length() - 1);

	}

	/*
	 * 产生后置任务工序字符串
	 */
	public void generateSuccOperationStr() {
		succOperationStr = "";
		for (SOperationLink link : this.succLinkSet) {
			// 必须在同一个零件任务之内
			// lqm todo
			// 20130806
			// 以后可能需要支持多种链接，比如工序与零件任务之间的链接
			String sp = link.getSuccOperationTask().getParentTaskUid();
			if (sp != null && !link.virtualLink && this.parentTaskUid != null
					&& sp.equals(this.parentTaskUid))
				succOperationStr += link.getSuccOperationTask()
						.getOperationIdDesc()
						+ ",";

		}
		if (succOperationStr.endsWith(","))
			succOperationStr = succOperationStr.substring(0, succOperationStr
					.length() - 1);

	}

	// @Override
	// public String getOutlineNumber() {
	// // TODO Auto-generated method stub
	// if(this.outlineNumber==null)
	// return String.valueOf(this.getOperationIdDesc());
	// else
	// return this.outlineNumber;
	// }

	/**
	 * @return the deptUid
	 */
	public String getDeptUid() {
		return deptUid;
	}

	/**
	 * @param deptUid
	 *            the deptUid to set
	 */
	public void setDeptUid(String deptUid) {
		this.deptUid = deptUid;
	}

	/**
	 * @return the masterShop
	 */
	public String getMasterShop() {
		return masterShop;
	}

	/**
	 * @param masterShop
	 *            the masterShop to set
	 */
	public void setMasterShop(String masterShop) {
		this.masterShop = masterShop;
	}

	/**
	 * @return the masterShopName
	 */
	public String getMasterShopName() {
		return masterShopName;
	}

	/**
	 * @param masterShopName
	 *            the masterShopName to set
	 */
	public void setMasterShopName(String masterShopName) {
		this.masterShopName = masterShopName;
	}

	public String getOperationIdDesc() {
		return operationIdDesc;
	}

	public void setOperationIdDesc(String operationIdDesc) {
		this.operationIdDesc = operationIdDesc;
	}

	/**
	 * @return the opUid
	 */
	public String getOpUid() {
		return opUid;
	}

	/**
	 * @param opUid
	 *            the opUid to set
	 */
	public void setOpUid(String opUid) {
		this.opUid = opUid;
	}

	/**
	 * @return the batchNum
	 */
	public String getBatchNum() {
		return batchNum;
	}

	/**
	 * @param batchNum
	 *            the batchNum to set
	 */
	public void setBatchNum(String batchNum) {
		this.batchNum = batchNum;
	}

	/**
	 * @return the operationId
	 */
	public Float getOperationId() {
		return operationId == null ? 0 : operationId;
	}

	/**
	 * @param operationId
	 *            the operationId to set
	 */
	public void setOperationId(Float operationId) {
		this.operationId = operationId;
	}

	/**
	 * @return the parentTaskUid
	 */
	public String getParentTaskUid() {
		return parentTaskUid;
	}

	/**
	 * @param parentTaskUid
	 *            the parentTaskUid to set
	 */
	public void setParentTaskUid(String parentTaskUid) {
		this.parentTaskUid = parentTaskUid;

	}

	/**
	 * @return the parentTask
	 */
	public SPartTask getParentTask() {
		return parentTask;
	}

	/**
	 * @param parentTask
	 *            the parentTask to set
	 */
	public void setParentTask(SPartTask parentTask) {
		this.parentTask = parentTask;

		this.parentTaskUid = parentTask == null ? null : parentTask
				.getTaskUid();
	}

	/**
	 * @return the alarmLevel
	 */
	public int getAlarmLevel() {
		return alarmLevel;
	}

	/**
	 * @param alarmLevel
	 *            the alarmLevel to set
	 */
	public void setAlarmLevel(int alarmLevel) {
		this.alarmLevel = alarmLevel;
	}

	/**
	 * @return the constraintType
	 */
	public int getConstraintType() {
		return constraintType;
	}

	/**
	 * @param constraintType
	 *            the constraintType to set
	 */
	public void setConstraintType(int constraintType) {
		this.constraintType = constraintType;
	}

	/**
	 * @return the constraintDate
	 */
	public Date getConstraintDate() {
		return constraintDate;
	}

	/**
	 * @param constraintDate
	 *            the constraintDate to set
	 */
	public void setConstraintDate(Date constraintDate) {
		this.constraintDate = constraintDate;
	}

	/**
	 * @return the deviceUid
	 */
	public String getDeviceUid() {
		return deviceUid;
	}

	/**
	 * @param deviceUid
	 *            the deviceUid to set
	 */
	public void setDeviceUid(String deviceUid) {
		this.deviceUid = deviceUid;
	}

	/**
	 * @return the deviceClass
	 */
	//为什么没有写deviceclass属性？直接获取的话可以吗？在hibernate注解识别的时候会自动创建吗？
	public String getDeviceClass() {
		return this.workCenterUid;
	}

	/**
	 * @param deviceClass
	 *            the deviceClass to set
	 */
	public void setDeviceClass(String deviceClass) {
		this.workCenterUid = deviceClass;
	}

	/**
	 * @return the device
	 */
	public SDevice getDevice() {
		return device;
	}

	/**
	 * @param device
	 *            the device to set
	 */
	public void setDevice(SDevice device) {
		this.device = device;
	}

	/**
	 * @return the indexForMultiCapacityDevice
	 */
	public int getIndexForMultiCapacityDevice() {
		return indexForMultiCapacityDevice;
	}

	/**
	 * @param indexForMultiCapacityDevice
	 *            the indexForMultiCapacityDevice to set
	 */
	public void setIndexForMultiCapacityDevice(int indexForMultiCapacityDevice) {
		this.indexForMultiCapacityDevice = indexForMultiCapacityDevice;
	}

	/**
	 * @return the earlyStart
	 */
	public Date getEarlyStart() {
		return earlyStart;
	}

	/**
	 * @param earlyStart
	 *            the earlyStart to set
	 */
	public void setEarlyStart(Date earlyStart) {
		this.earlyStart = earlyStart;
	}

	/**
	 * @return the lateFinish
	 */
	public Date getLateFinish() {
		return lateFinish;
	}

	/**
	 * @param lateFinish
	 *            the lateFinish to set
	 */
	public void setLateFinish(Date lateFinish) {
		this.lateFinish = lateFinish;
	}

	/**
	 * @return the planStart
	 */
	public Date getPlanStart() {
		return planStart;
	}

	/**
	 * @param planStart
	 *            the planStart to set
	 */
	public void setPlanStart(Date planStart) {
		// if(this.taskUid.equals("012db128-f3ce-4dad-97ae-aa5c9d4b5c1a"))
		// {
		// System.out.println("aaaaaaaaaaaa");
		// }
		this.planStart = planStart;
	}

	/**
	 * @return the planFinish
	 */
	public Date getPlanFinish() {
		return planFinish;
	}

	/**
	 * @param planFinish
	 *            the planFinish to set
	 */
	public void setPlanFinish(Date planFinish) {

		// if (this.taskUid.equals(
		// "3787238")
		//
		// ) {
		// System.out.println("****************设置日期为:"+planFinish );
		//
		// }

		this.planFinish = planFinish;
	}

	public Date getControlEarlyStart() {
		return controlEarlyStart;
	}

	public void setControlEarlyStart(Date controlEarlyStart) {
		this.controlEarlyStart = controlEarlyStart;
	}

	/**
	 * @return the controlFinish 应该换成deadline更合适一些
	 */
	
	public Date getControlFinish() {
		Date dtFinish = this.scheme.getScheduleFinish();
		if (this.parentTask != null && this.parentTask.getLateFinish() != null) {
			if (this.getLateFinish() != null
					&& this.getLateFinish().before(
							this.parentTask.getLateFinish())) {
				dtFinish = this.getLateFinish();
			} else {
				dtFinish = this.parentTask.getLateFinish();
			}
		} else {
			if (this.getLateFinish() != null) {
				dtFinish = this.getLateFinish();
			}
		}

		return dtFinish;
	}
	

	/**
	 * @return the estiTaskWork
	 */
	public Double getEstiTaskWork() {
		return estiTaskWork == null ? 0 : estiTaskWork;
	}

	/**
	 * @param estiTaskWork
	 *            the estiTaskWork to set
	 */
	public void setEstiTaskWork(Double estiTaskWork) {
		this.estiTaskWork = estiTaskWork;
	}

	/**
	 * @return the estiPreTime
	 */
	public Double getEstiPreTime() {
		return estiPreTime == null ? 0 : estiPreTime;
	}

	/**
	 * @param estiPreTime
	 *            the estiPreTime to set
	 */
	public void setEstiPreTime(Double estiPreTime) {
		this.estiPreTime = estiPreTime;
	}

	/**
	 * @return the estiRunTime
	 */
	public Double getEstiRunTime() {
		return estiRunTime == null ? 0 : estiRunTime;
	}

	/**
	 * @param estiRunTime
	 *            the estiRunTime to set
	 */
	public void setEstiRunTime(Double estiRunTime) {
		this.estiRunTime = estiRunTime;
	}

	public Integer getAssignState() {
		return assignState == null ? SOperationTask.ASSNSTATE_WAITING
				: assignState;
	}

	public void setAssignState(Integer assignState) {
		this.assignState = assignState;
	}

	/**
	 * @return the ready
	 */
	public boolean isReady() {
		return ready;
	}

	/**
	 * @param ready
	 *            the ready to set
	 */
	public void setReady(boolean ready) {
		this.ready = ready;
	}

	/**
	 * @return the warning
	 */
	public boolean isWarning() {
		return warning;
	}

	/**
	 * @param warning
	 *            the warning to set
	 */
	public void setWarning(boolean warning) {
		this.warning = warning;
	}

	public SGroupOperationTask getGroupTask() {
		return groupTask;
	}

	public void setGroupTask(SGroupOperationTask groupTask) {
		this.groupTask = groupTask;
	}

	/**
	 * @return the isPSOperation
	 */
	public boolean isPSOperation() {
		return isPSOperation;
	}

	/**
	 * @param isPSOperation
	 *            the isPSOperation to set
	 */
	public void setPSOperation(boolean isPSOperation) {
		this.isPSOperation = isPSOperation;
	}

	/**
	 * @return the taskDistance
	 */
	public int getTaskDistance() {
		return taskDistance;
	}

	/**
	 * @param taskDistance
	 *            the taskDistance to set
	 */
	public void setTaskDistance(int taskDistance) {
		this.taskDistance = taskDistance;
	}

	/**
	 * @return the waitTime
	 */
	public double getWaitTime() {
		return waitTime;
	}

	/**
	 * @param waitTime
	 *            the waitTime to set
	 */
	public void setWaitTime(double waitTime) {
		this.waitTime = waitTime;
	}

	/**
	 * @return the predLinkSet
	 */
	public Set<SOperationLink> getPredLinkSet() {
		// 这句话是否加上存在一些疑虑
		// lqm todo
		if (this.groupTask != null)
			return this.groupTask.getPredLinkSet();

		return predLinkSet;
	}

	/**
	 * @param predLinkSet
	 *            the predLinkSet to set
	 */
	public void setPredLinkSet(Set<SOperationLink> predLinkSet) {
		this.predLinkSet = predLinkSet;

	}

	/**
	 * @return the succLinkSet
	 */
	public Set<SOperationLink> getSuccLinkSet() {
		// 这句话是否加上存在一些疑虑
		// lqm todo
		if (this.groupTask != null)
			return this.groupTask.getSuccLinkSet();
		return succLinkSet;
	}

	/**
	 * @param succLinkSet
	 *            the succLinkSet to set
	 */
	public void setSuccLinkSet(Set<SOperationLink> succLinkSet) {

		this.succLinkSet = succLinkSet;
	}

	public Map<String, ResourceConstraint> getAlterResourceMap() {
		return alterResourceMap;
	}

	public void setAlterResourceMap(
			Map<String, ResourceConstraint> alterResourceMap) {
		this.alterResourceMap = alterResourceMap;
	}

	public int getAssnPriority() {
		return assnPriority;
	}

	public void setAssnPriority(int assnPriority) {
		this.assnPriority = assnPriority;
	}

	public String getDeviceClassName() {
		return deviceClassName;
	}

	public void setDeviceClassName(String deviceClassName) {
		this.deviceClassName = deviceClassName;
	}

	public String getPredOperationStr() {

		return predOperationStr;
	}

	public void setPredOperationStr(String predOperationStr) {
		this.predOperationStr = predOperationStr;
	}

	public String getSuccOperationStr() {
		return succOperationStr;
	}

	public void setSuccOperationStr(String succOperationStr) {
		this.succOperationStr = succOperationStr;
	}

	public String getPartUid() {
		return partUid;
	}

	public void setPartUid(String partUid) {
		this.partUid = partUid;
	}

	/*
	 * 计算工时 应该移入operationTaskManager
	 */
	public void calTaskWork() {
		// 2071表示完成准备
		if (this.planQty == null || this.planQty == 0)
			return;

		double completeQty = this.completeQty == null ? 0 : this.completeQty;
		double estiPreTime = this.estiPreTime == null ? 0 : this.estiPreTime;
		double estiRunTime = this.estiRunTime == null ? 0 : this.estiRunTime;
		double estiDelayTime = this.estiDelayTime == null ? 0 : this.estiDelayTime;
		if (completeQty >= planQty)
			this.estiTaskWork = 0d;
		else if (completeQty > 0
				|| (this.taskState != null && this.taskState == SOperationTask.TASKSTATE_PREPARE_COMPLETED))
			this.estiTaskWork = (this.planQty - completeQty) * estiRunTime;
		else
			this.estiTaskWork = estiPreTime + (this.planQty - completeQty)
					* estiRunTime;
		this.estiTaskWork+=estiDelayTime;
		
		this.shiftsCount = this.estiTaskWork == null ? 0
				: this.estiTaskWork / 450;

	}

	public Double getShiftsCount() {
		// todo
		// 有的班次是480分钟，有的班次是420分钟，取折中
		// 这个信息主要用于输出报表，属于比较临时的字段

		return shiftsCount;
	}

	public void setShiftsCount(Double shiftsCount) {
		this.shiftsCount = shiftsCount;
	}

	// @Override
	// public Integer getPriority() {
	// // 暂时工序任务直接取零件任务的优先级
	// // if (parentTask != null)
	// // return parentTask.getPriority();
	//
	// return super.getPriority();
	// }

	@Override
	public Double getSlackFactor() {
		// 暂时工序任务直接取零件任务的优先级
		// if (parentTask != null)
		// return parentTask.getSlackFactor();
		return super.getSlackFactor();
	}

	public String getDrawingId() {
		// 暂时工序任务直接取零件任务的图号

		if (parentTask != null)
			return parentTask.getDrawingId();

		return this.drawingId;
	}

	public void setDrawingId(String drawingId) {
		this.drawingId = drawingId;
	}

	public Date getActualPrepareFinish() {
		return actualPrepareFinish;
	}

	public void setActualPrepareFinish(Date actualPrepareFinish) {
		this.actualPrepareFinish = actualPrepareFinish;
	}

	public Date getActualFirstFinish() {
		return actualFirstFinish;
	}

	public void setActualFirstFinish(Date actualFirstFinish) {
		this.actualFirstFinish = actualFirstFinish;
	}

	public int getMaturity() {
		// 暂时工序任务直接取零件任务的优先级
		// lqm todo
		// 临时指令
		if (this.batchNum != null && this.batchNum.indexOf("P") > 0)
			return 1;
		else
			return 0;
	}

	
	public Date getPredFinish() {
		Date predFinish = null;

		predFinish = scheme.getScheduleStart();
		// 取得前置任务链接用getpredlinkset,而不是直接用this.predlinkset，
		// 这样主要是为了继承对getlinkset进行了扩展
		for (SOperationLink link : this.getPredLinkSet()) {
			SOperationTask so = link.getPredOperationTask();
			if (so.getPlanFinish() != null
					&& so.getPlanFinish().after(predFinish))
				predFinish = so.getPlanFinish();
		}

		return predFinish;
	}
	
	
	public Date getSuccStart() {
		Date succStart = null;

		succStart = scheme.scheduleFinish;
		for (SOperationLink link : this.getSuccLinkSet()) {
			SOperationTask so = link.getSuccOperationTask();
			if (so.getPlanStart() != null
					&& so.getPlanStart().before(succStart))
				succStart = so.getPlanStart();
		}

		return succStart;
	}

	public Integer getDeviceSeq() {
		return deviceSeq;
	}

	public void setDeviceSeq(Integer deviceSeq) {
		this.deviceSeq = deviceSeq;
	}

	public void setMaturity(int maturity) {
		this.maturity = maturity;
	}

	public String getGroupTaskUid() {
		return groupTaskUid;
	}

	public void setGroupTaskUid(String groupTaskUid) {
		this.groupTaskUid = groupTaskUid;
	}

	public String getPartName() {
		if (parentTask != null)
			return parentTask.getPartName();
		return partName;
	}

	public void setPartName(String partName) {
		this.partName = partName;
	}

	/*
	 * 如果属于协作，则返回协作工作中心
	 */

	public String getDeptName() {
		return deptName;
	}

	public void setDeptName(String deptName) {
		this.deptName = deptName;
	}

	public List<SOperationTask> getSubTasks() {
		return subTasks;
	}

	public void setSubTasks(List<SOperationTask> subTasks) {
		this.subTasks = subTasks;
	}

	public Date getCoPlanFinish() {
		return coPlanFinish;
	}

	public Date getCoPlanStart() {
		return coPlanStart;
	}

	public void setCoPlanFinish(Date coPlanFinish) {
		this.coPlanFinish = coPlanFinish;
	}

	public void setCoPlanStart(Date coPlanStart) {
		this.coPlanStart = coPlanStart;
	}

	public Date getPrevPlanStart() {
		return prevPlanStart;
	}

	public void setPrevPlanStart(Date prevPlanStart) {
		this.prevPlanStart = prevPlanStart;
	}

	public Date getPrevPlanFinish() {
		return prevPlanFinish;
	}

	public void setPrevPlanFinish(Date prevPlanFinish) {
		this.prevPlanFinish = prevPlanFinish;
	}

	@Override
	public Integer getCalPriority() {

		return this.calPriority == null ? this.priority : this.calPriority;
	}

	public String getTaskStateDesc() {
		String taskStateDesc = "";
		switch (this.taskState) {
		case 201:
			taskStateDesc = "草稿";
			break;

		case 202:
			taskStateDesc = "已分解";
			break;
		case 204:
			taskStateDesc = "已计划";
			break;
		case 205:
			taskStateDesc = "已计划";
			break;

		case 206:
			taskStateDesc = "已派工";
			break;
		case 2061:
			taskStateDesc = "开始准备";
			break;
		case 2069:
			taskStateDesc = "完成准备";
			break;
		case 207:
			taskStateDesc = "已开始";
			break;
		case 2071:
			taskStateDesc = "已三检";
			break;
		case 2073:
			taskStateDesc = "正常加工";
			break;
		case 208:
			taskStateDesc = "已暂停";
			break;
		case 2081:
			taskStateDesc = "已中断";
			break;
		case 210:
			taskStateDesc = "已取消";
			break;
		default:
			taskStateDesc = "无";
			break;
		}

		return taskStateDesc;

	}

	public Date getPlanFirstCheckStart() {
		return planFirstCheckStart;
	}

	public void setPlanFirstCheckStart(Date planFirstCheckStart) {
		this.planFirstCheckStart = planFirstCheckStart;
	}

	@Override
	public String getUuid() {
		// TODO Auto-generated method stub
		return this.scheduleUid + "___" + this.taskUid;
	}

	@Override
	public void setUuid(String uuid) {
		// // TODO Auto-generated method stub
		// super.setUuid(uuid);
	}

	// 临时先这么用
	// todo
	
	public String getSWorkCenterUid() {
		//
		// if
		// (this.masterShop!=null&&scheme.getDeptUid().equals(this.masterShop)
		// && scheme.getWorkCenterMap().containsKey(this.getDeviceClass())) {
		// return this.deviceClass;
		//
		// }
		return this.getDeviceClass() == null ? scheme.getVirtualCoWorkCenter().workCenterUid
				: this.getDeviceClass();

	}

	public void setSWorkCenterUid(String workCenterUid) {
		sWorkCenterUid = workCenterUid;
	}

	// 临时先这么用
	// todo
	public SWorkCenter getSWorkCenter() {

		if (this.workCenterUid != null
				&& scheme.getWorkCenterMap().containsKey(this.workCenterUid)) {
			return scheme.workCenterMap.get(this.workCenterUid);

		}
		return scheme.virtualCoWorkCenter;
	}

	public void setSWorkCenter(SWorkCenter workCenter) {
		sWorkCenter = workCenter;
	}

	public void setCoTaskState(Integer coTaskState) {
		this.coTaskState = coTaskState;
	}

	public Integer getCoTaskState() {
		return coTaskState;
	}

	public List<Integer> getUseSegementList() {
		return useSegementList;
	}

	public void setUseSegementList(List<Integer> useSegementList) {
		this.useSegementList = useSegementList;
	}

	public Resource getAssignedResource() {
		return assignedResource;
	}

	public void setAssignedResource(Resource assignedResource) {
		this.assignedResource = assignedResource;
	}

	public Date getCalcEarlyStart() {
		return calcEarlyStart;
	}

	public void setCalcEarlyStart(Date calcEarlyStart) {
//		if(taskUid.equals("29d7e392-3c1e-4757-a0c7-c2672a6ed99c") &&this.scheme!=null )
//		{
//			Calendar c=Calendar.getInstance();
//			c.setTime(scheme.getScheduleCurrentTime());
//			c.add(5,Calendar.DAY_OF_YEAR);
//			if(calcEarlyStart.after(c.getTime()))
//			{
//				System.out.println("aaaaaaaaaaaaaaa");
//			}
//		}
		
		this.calcEarlyStart = calcEarlyStart;
	}

	public CheckPoint getCheckPoint() {
		return checkPoint;
	}

	public void setCheckPoint(CheckPoint checkPoint) {
		this.checkPoint = checkPoint;
	}

	// 整个零件的剩余工时
	public Double getRemainWork() {
		return remainWork == null ? 0 : remainWork;
	}

	public void setRemainWork(Double remainWork) {
		this.remainWork = remainWork;
	}

	public int getScheduleOrder() {
		return scheduleOrder;
	}

	public void setScheduleOrder(int scheduleOrder) {
		this.scheduleOrder = scheduleOrder;
	}

	public Integer getCalDeviceSeq() {
		// 以后编程时尽量不要用这种方法
		// 保持pojo类的单纯
		// 同时避免一些不必要的错误
		// lqm todo
		// return this.calDeviceSeq==null?this.deviceSeq:calDeviceSeq;

		return calDeviceSeq;
	}

	public void setCalDeviceSeq(Integer calDeviceSeq) {
		this.calDeviceSeq = calDeviceSeq;
	}

	public int getPlanFinishSegment() {
		return planFinishSegment;
	}

	public void setPlanFinishSegment(int planFinishSegment) {
		this.planFinishSegment = planFinishSegment;
	}

	public int getPlanStartSegment() {
		return planStartSegment;
	}

	public void setPlanStartSegment(int planStartSegment) {
		this.planStartSegment = planStartSegment;
	}

	public int getScheduleCount() {
		return scheduleCount;
	}

	public void setScheduleCount(int scheduleCount) {
		this.scheduleCount = scheduleCount;
	}

	public Boolean getCalAllowCancelAssign() {
		return calAllowCancelAssign;
	}

	public void setCalAllowCancelAssign(Boolean calAllowCancelAssign) {
		this.calAllowCancelAssign = calAllowCancelAssign;
	}

	public String getWorkCenterUid() {
		return workCenterUid;
	}

	public void setWorkCenterUid(String workCenterUid) {
		this.workCenterUid = workCenterUid;
	}

	public WorkCenter getWorkCenter() {
		return workCenter;
	}

	public void setWorkCenter(WorkCenter workCenter) {
		this.workCenter = workCenter;
	}

	public Date getBaseStart() {
		return baseStart;
	}

	public void setBaseStart(Date baseStart) {
		this.baseStart = baseStart;
	}

	public Date getBaseFinish() {
		return baseFinish;
	}

	public void setBaseFinish(Date baseFinish) {
		this.baseFinish = baseFinish;
	}

	public Part getPart() {
		return part;
	}

	public void setPart(Part part) {
		this.part = part;
	}





	public String getCalFixedDeviceUid() {
		return calFixedDeviceUid;
	}

	public void setCalFixedDeviceUid(String calFixedDeviceUid) {
		this.calFixedDeviceUid = calFixedDeviceUid;
	}


	@Override
	public void destroy() {
		try {
			// TODO Auto-generated method stub
			super.destroy();
			if (this.predLinkSet != null) {
				this.predLinkSet.clear();
				this.predLinkSet = null;
			}
			if (this.succLinkSet != null) {
				this.succLinkSet.clear();
				this.succLinkSet = null;
			}
			if (this.alterResourceMap != null) {
				this.alterResourceMap.clear();
				this.alterResourceMap = null;
			}
			if (this.useSegementList != null) {
				this.useSegementList.clear();
				this.useSegementList = null;
			}
			if (this.taskAssignLock != null)
				this.taskAssignLock = null;
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public Double getEstiDelayTime() {
		return estiDelayTime;
	}

	public void setEstiDelayTime(Double estiDelayTime) {
		this.estiDelayTime = estiDelayTime;
	}

	public Date getCalcEarlyFinish() {
		return calcEarlyFinish;
	}

	public void setCalcEarlyFinish(Date calcEarlyFinish) {
		this.calcEarlyFinish = calcEarlyFinish;
	}

	public Boolean getCanChangeDevice() {
		return canChangeDevice;
	}

	public void setCanChangeDevice(Boolean canChangeDevice) {
		this.canChangeDevice = canChangeDevice;
	}

	public double getCalAtcValue() {
		return calAtcValue;
	}

	public void setCalAtcValue(double calAtcValue) {
		this.calAtcValue = calAtcValue;
	}

	
}
